#include "StdAfx.h"
#include "HookJump.h"

/* CHookJump modified from taksi project: BSD license */
bool CHookJump::InstallHook( LPVOID pFunc, LPVOID pFuncNew )
{
    if (pFunc == NULL)
		return false;
    
	if (IsHookInstalled() && ! memcmp(pFunc, m_jump, sizeof(m_jump)))
        return true;

    m_jump[0] = 0;

    DWORD dwNewProtection = PAGE_EXECUTE_READWRITE;
    if (!::VirtualProtect(pFunc, 8, dwNewProtection, &m_dwOldProtection))
            return false;

    /* unconditional JMP to relative address is 5 bytes */
    m_jump[0] = 0xE9;
    DWORD dwAddr = (DWORD)((UINT_PTR)pFuncNew - (UINT_PTR)pFunc) - sizeof(m_jump);
    memcpy(m_jump+1, &dwAddr, sizeof(dwAddr));
    memcpy(m_oldCode, pFunc, sizeof(m_oldCode));
    memcpy(pFunc, m_jump, sizeof(m_jump));

    return true;
}

void CHookJump::RemoveHook( LPVOID pFunc )
{
    if (pFunc == NULL)
		return;

	/* was never set! */
    if (!IsHookInstalled())       
        return;

    try
    {
        memcpy(pFunc, m_oldCode, sizeof(m_oldCode));    /* SwapOld(pFunc) */
        DWORD dwOldProtection = 0;
        ::VirtualProtect(pFunc, 8, m_dwOldProtection, &dwOldProtection ); /* restore protection */
        m_jump[0] = 0;
    }
    catch (...)
    {}
}
